/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package be.ugent.medirem.logic;

import be.ugent.medirem.persistence.entity.details.MedicationTaskDetails;
import be.ugent.medirem.persistence.entity.details.PrescriptionDetails;
import be.ugent.medirem.persistence.entity.values.MedicationTaskValues;
import be.ugent.medirem.persistence.exception.EntityNotFoundException;
import be.ugent.medirem.persistence.facade.MedicationTaskDaoLocal;
import be.ugent.medirem.persistence.facade.PrescriptionDaoLocal;
import be.ugent.medirem.persistence.util.TaskStatus;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Stateless;

/**
 *
 * @author Thomas Roelens
 */
@Stateless
public class TaskBean implements TaskRemote {

    @EJB
    private PrescriptionDaoLocal prescriptionDaoBean;
    @EJB
    private MedicationTaskDaoLocal medicationTaskDaoBean;

    public Long createTask(MedicationTaskValues details) throws IllegalArgumentException {
        return medicationTaskDaoBean.create(details);
    }

    public void removeTask(Long taskId) throws IllegalArgumentException, EntityNotFoundException {
        medicationTaskDaoBean.remove(taskId);
    }

    public void updateTask(Long taskId, MedicationTaskValues details) throws IllegalArgumentException, EntityNotFoundException {
        medicationTaskDaoBean.update(taskId, details);
    }

    public void updateTaskStatus(Long taskId, Long patientId, TaskStatus status) throws IllegalArgumentException, EntityNotFoundException {

        if (status == TaskStatus.NOT_COMPLETED) {
            medicationTaskDaoBean.updateStatus(taskId, status);
            return;
        }

        // If we complete the task, we should make a new Task with the next suggested time
        // The end time is now
        Date now = new Date();

        // Complete the task with the right status and the current time as end time
        this.updateTask(taskId, new MedicationTaskValues(null, null, status, null, now));

        // We should now make the following task for this prescription
        MedicationTaskDetails prevTaskDetails = medicationTaskDaoBean.getDetails(taskId);
        PrescriptionDetails prescr = prevTaskDetails.getPrescription();

        // Calculate the next task time 
        Date nextTime = this.calculateNextTaskTime(prescr.getPrescriptionId(), now);

        // Only make a new task if the end time of this prescription has not yet passed
        if (nextTime.before(prescr.getEndTime())) {
            medicationTaskDaoBean.create(new MedicationTaskValues(prescr.getPrescriptionId(), nextTime));
        }
    }

    /**
     * Logic method: Calculate the next task time based on the prescription frequency
     *
     * @param prescriptionId The id of the prescription the task is linked to
     * @param endTime The time the previous task was completed
     * @return The Date the nex task should be completed
     * @throws EntityNotFoundException
     * @throws IllegalArgumentException
     */
    private Date calculateNextTaskTime(Long prescriptionId, Date endTime) throws EntityNotFoundException, IllegalArgumentException {
        if (prescriptionId == null) {
            throw new IllegalArgumentException("Prescription id is null");
        }
        PrescriptionDetails p = prescriptionDaoBean.getDetails(prescriptionId);
        if (p == null) {
            throw new EntityNotFoundException("Prescription not found with id " + prescriptionId);
        }
        double frequency = p.getFrequency();

        return new Date((long) (endTime.getTime() + frequency * 3600 * 1000));

    }

    public MedicationTaskDetails getTaskDetails(Long taskId) throws IllegalArgumentException, EntityNotFoundException {
        return medicationTaskDaoBean.getDetails(taskId);
    }

    public List<String> getAllTaskStatus() {
        return medicationTaskDaoBean.getAllTaskStatus();
    }

    public List<MedicationTaskDetails> getAllTasks(Long patientId) throws IllegalArgumentException, EntityNotFoundException {
        return medicationTaskDaoBean.getAllTasks(patientId);
    }

    public MedicationTaskDetails getNextTask(Long patientId, Long prescriptionId) throws IllegalArgumentException, EntityNotFoundException {
        return medicationTaskDaoBean.getNextTask(patientId, prescriptionId);
    }

    public List<MedicationTaskDetails> getAllCompletedTasks(Long patientId) throws IllegalArgumentException, EntityNotFoundException {
        return medicationTaskDaoBean.getTasks(patientId, TaskStatus.COMPLETED);
    }

    public List<MedicationTaskDetails> getAllIncompletedTasks(Long patientId) throws IllegalArgumentException, EntityNotFoundException {
        return medicationTaskDaoBean.getTasks(patientId, TaskStatus.NOT_COMPLETED);
    }

    public List<MedicationTaskDetails> getMissedTasks(Long patientId) throws IllegalArgumentException, EntityNotFoundException {
        List<MedicationTaskDetails> taskList = this.getAllIncompletedTasks(patientId);
        List<MedicationTaskDetails> missedTaskList = new ArrayList<MedicationTaskDetails>();

        Date currentTime = new Date();

        for (MedicationTaskDetails task : taskList) {
            Date taskTime = task.getTaskTime();
            // A missed task is incomplete and happened before now
            if (taskTime.before(currentTime)) {
                missedTaskList.add(task);
            }
        }

        return missedTaskList;
    }

    public List<MedicationTaskDetails> getTasks(Long patientId, Long prescriptionId) throws IllegalArgumentException, EntityNotFoundException {

        List<MedicationTaskDetails> list = medicationTaskDaoBean.getTasks(patientId, prescriptionId);

        Collections.sort(list, new Comparator<MedicationTaskDetails>() {

            public int compare(MedicationTaskDetails o1, MedicationTaskDetails o2) {
                return (o1.getTaskTime()).compareTo(o2.getTaskTime());
            }
        });


        return list;
    }

    public List<MedicationTaskDetails> getAllUnseenTasks(Long patient) {
        try {
            return medicationTaskDaoBean.getTasks(patient, TaskStatus.NOT_SEEN);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(TaskBean.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        } catch (EntityNotFoundException ex) {
            Logger.getLogger(TaskBean.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
}
